# 版本: 1.0.0.20250825
# 作者: 陈振玺
# 功能: PCA图表绘制工具，支持自定义元数据映射

r_vizcraft_pca_visualizer <- function(data_path, metadata_end_col, color_var = NULL, shape_var = NULL, output_dir = "./pca_output") {
  # 检查必要包是否已安装
  required_packages <- c("readxl", "readr", "dplyr", "ggplot2", "FactoMineR", "factoextra")
  for (pkg in required_packages) {
    if (!requireNamespace(pkg, quietly = TRUE)) {
      stop(paste0("包 ", pkg, " 未安装，请先安装该包"))
    }
  }
  
  # 根据文件扩展名读取数据
  if (grepl("\\.xlsx?$", data_path, ignore.case = TRUE)) {
    data <- readxl::read_excel(data_path)
  } else if (grepl("\\.csv$", data_path, ignore.case = TRUE)) {
    data <- readr::read_csv(data_path)
  } else {
    stop("不支持的文件格式，请提供Excel或CSV文件")
  }
  
  # 检查元数据结束列是否存在
  if (metadata_end_col > ncol(data)) {
    stop("指定的元数据结束列超出了数据列数")
  }
  
  # 分离元数据和特征数据
  metadata <- data[, 1:metadata_end_col, drop = FALSE]
  feature_data <- data[, (metadata_end_col + 1):ncol(data), drop = FALSE]
  
  # 检查特征数据是否为空
  if (ncol(feature_data) == 0) {
    stop("未找到特征数据，请检查元数据结束列的指定是否正确")
  }
  
  # 检查颜色和形状变量是否存在
  if (!is.null(color_var) && !(color_var %in% names(metadata))) {
    stop(paste0("颜色变量 ", color_var, " 不存在于元数据中"))
  }
  
  if (!is.null(shape_var) && !(shape_var %in% names(metadata))) {
    stop(paste0("形状变量 ", shape_var, " 不存在于元数据中"))
  }
  
  # 创建输出目录
  if (!dir.exists(output_dir)) {
    dir.create(output_dir, recursive = TRUE)
  }
  
  # 执行PCA分析
  # 将特征数据转换为矩阵并确保是数值型
  feature_matrix <- as.matrix(feature_data)
  feature_matrix <- apply(feature_matrix, 2, as.numeric)
  
  # 检查是否有非数值列
  if (any(is.na(feature_matrix))) {
    stop("特征数据中包含非数值型数据，请确保所有特征列都是数值型")
  }
  
  # 进行PCA分析
  pca_result <- FactoMineR::PCA(feature_matrix, graph = FALSE)
  
  # 提取主成分坐标
  pca_coords <- pca_result$ind$coord
  
  # 合并元数据与PCA坐标
  plot_data <- cbind(metadata, pca_coords)
  
  # 创建PCA图
  p <- factoextra::fviz_pca_ind(
    pca_result,
    geom.ind = "point",
    col.ind = if (!is.null(color_var)) plot_data[[color_var]] else "black",
    palette = if (!is.null(color_var)) NULL else NULL,
    pointshape = if (!is.null(shape_var)) plot_data[[shape_var]] else 19,
    legend.title = if (!is.null(color_var)) color_var else "Individuals",
    repel = TRUE
  ) +
  ggplot2::theme_minimal() +
  ggplot2::labs(title = "PCA分析图")
  
  # 保存图形
  output_file <- file.path(output_dir, "pca_plot.png")
  ggplot2::ggsave(output_file, plot = p, width = 8, height = 6, dpi = 300)
  cat(paste0("已保存PCA图到: ", output_file, "\n"))
  
  # 保存PCA结果摘要
  summary_file <- file.path(output_dir, "pca_summary.txt")
  sink(summary_file)
  print(summary(pca_result))
  sink()
  cat(paste0("已保存PCA摘要到: ", summary_file, "\n"))
  
  cat("PCA分析已完成\n")
  
  # 返回PCA结果供进一步使用
  invisible(list(pca_result = pca_result, plot_data = plot_data))
}